/**
  * Author: Mei
  * Date: 2020-12-30 19:13
  * Description: 遍历tuple
  *
  *
  */
#include "../head.h"

template<int... a>
struct IndexTuple { //一个中介  用来得到tuple所有的索引
    print() {
        cout << "sizeof:" << sizeof...(a);
    }
};

template<int N, int ... Indexes>
struct make_index : make_index<N - 1, N - 1, Indexes...> {
//struct make_index : make_index<N - 1, Indexes..., N - 1> { //索引的逆序

};
template<int ... indexes>
struct make_index<0, indexes...> {
    typedef IndexTuple<indexes...> type;
};

namespace details {
    template<typename Func, typename Last>
    void for_each_impl(Func &&f, Last &&last) {
        f(last);
    };

    template<typename Func, typename First, typename ...Rest>
    void for_each_impl(Func &&f, First &&first, Rest &&...rest) {
        f(first);
        for_each_impl(forward<Func>(f), forward<Rest>(rest)...);
    };

    template<typename Func, int ... Indexes, typename ...Args>
    void for_each_helper(Func &&f, IndexTuple<Indexes...>, tuple<Args...> &&tup) {
        //cout <<"sizeof: "<< sizeof...(Args) << endl;
        for_each_impl(forward<Func>(f),
                      forward<Args>(get<Indexes>(tup))...
                //get<Indexes>(tup)...  //反转tuple的话 不能用转发 会出现值和类型不匹配 只能左引用传值
        );
    }
}

//最终执行打印的
struct Functor {
    template<typename T>
    void operator()(T &t) {
        cout << t << endl;
    }
};

template<typename F, typename Tuple>
void tp_for_each(F &&f, Tuple &tup) {
    //cout << tuple_size<Tuple>::value << endl;
    using namespace details;
    for_each_helper(
            forward<F>(f),
            typename make_index<tuple_size<Tuple>::value>::type(),
            move(tup));
}

template<typename Func, typename ... Args>
void tp_for_each(Func &&f, tuple<Args...> &&tup) {
    using namespace details;
    for_each_helper(
            forward<Func>(f),
            typename make_index<tuple_size<tuple<Args...>>::value>::type(),
            forward<tuple<Args...>>(tup));
}

void TestTupleForeach() {
    tuple<int, short, double, char, int, bitset<8>> tp = make_tuple(1, 2, 3, 'a', 10, 29);
    tp_for_each(Functor(),
                make_tuple<int, short, double, char, int, bitset<8>>(1, 2, 3, 'a', 10, 29));
}

int main() {
    TestTupleForeach();

    return 0;
}